<?php

namespace app\demo\service\user_demo;

use app\demo\enum\Sex;
use app\demo\enum\Grade;
use app\demo\enum\Hobby;
use app\demo\enum\State;
use app\demo\model\User as UserModel;
use app\demo\model\InterestCate as InterestCateModel;

final class Index {

    /**
     * @var UserModel
     */
    private $userModel;

    /**
     * @var InterestCateModel
     */
    private $interestCateModel;

    /**
     * @return UserModel
     */
    public function getUserModel(): UserModel {
        if (!$this->userModel) $this->setUserModel();
        return $this->userModel;
    }

    /**
     * @param UserModel $userModel
     */
    public function setUserModel(UserModel $userModel = null): void {
        $this->userModel = $userModel ?: (new UserModel());
    }

    /**
     * @return InterestCateModel
     */
    public function getInterestCateModel(): InterestCateModel {
        if (!$this->interestCateModel) $this->setInterestCateModel();
        return $this->interestCateModel;
    }

    /**
     * @param InterestCateModel $interestCateModel
     */
    public function setInterestCateModel(InterestCateModel $interestCateModel = null): void {
        $this->interestCateModel = $interestCateModel ?: (new InterestCateModel());
    }

    private static $instance;

    public static function getInstance() {
        if (!self::$instance instanceof self) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * Notes: 状态栏
     * Author: Uncle-L
     * Date: 2021/11/14
     * Time: 13:33
     * @return array
     */
    public function state(): array {
        return State::getTableState();
    }

    /**
     * Notes: 筛选表单
     * Author: Uncle-L
     * Date: 2021/11/15
     * Time: 11:59
     * @param $state
     * @return array
     */
    public function filter($state): array {
        $filter = [
            'name' => ['title' => '姓名'],
            'grade' => [
                'title' => '年级',
                'type' => 'select',
                'options' => [0 => '请选择'] + Grade::getTitleMap()
            ],
        ];
        return $filter;
    }

    /**
     * Notes: 头部工具栏
     * Author: Uncle-L
     * Date: 2021/11/15
     * Time: 14:36
     * @param $state
     * @return array
     */
    public function toolbar($state): array {
        $toolbar = ['add' => ['type' => 'openPopup', 'title' => '添加', 'class' => 'layui-icon layui-icon-add-circle', 'url' => url('add')]];
        switch ($state) {
            case State::NORMAL:
                $toolbar += [
                    State::RECYLE_BIN => ['title' => '移入回收站', 'dropdown' => true],
                ];
                break;
            case State::RECYLE_BIN:
                $toolbar += [
                    State::NORMAL => ['title' => '恢复正常', 'dropdown' => true],
                    State::DELETED => ['title' => '永久删除', 'dropdown' => true],
                ];
                break;
        }
        return $toolbar;
    }

    /**
     * Notes: 头部右侧工具栏
     * Author: Uncle-L
     * Date: 2021/11/15
     * Time: 14:36
     * @param $state
     * @return array
     */
    public function defaultToolbar($state): array {
        return ['filter', 'export', 'print', 'import'];
    }

    /**
     * Notes: 表头
     * Author: Uncle-L
     * Date: 2021/11/14
     * Time: 13:42
     * @param $state [状态]
     * @return array
     */
    public function cols($state): array {
        $cols = [
            'id' => [
                'type' => 'checkbox',
                'fixed' => "left"
            ],
            'avatar' => [
                'title' => '头像',
                "templet" => "img",
                "align" => "center"
            ],
            'name' => ['title' => '姓名'],
            'sex' => [
                'title' => '性别',
                "templet" => "enum",
                "options" => Sex::getTitleMap(),
                "align" => "center"
            ],
            'age' => [
                'title' => '年龄',
                "align" => "center"
            ],
            'grade' => [
                'title' => '年级',
                "templet" => "enum",
                "options" => Grade::getTitleMap(),
                "align" => "center"
            ],
            'color' => [
                'title' => '喜欢的颜色',
                "templet" => "color"
            ],
            "album" => [
                'title' => '相册',
                "templet" => "imgs"
            ],
            "hobby" => [
                'title' => '爱好',
                "templet" => "enum",
                "options" => Hobby::getTitleMap()
            ],
            "interest_cate_ids" => [
                'title' => '兴趣分类',
                "templet" => "enum",
                "options" => $this->getInterestCateIdNameOptions()
            ],
            'area' => [
                'title' => '地址',
                'templet' => 'area',
                'hide' => 'yes',
            ],
            'document' => [
                'title' => '个人文档',
                'templet' => 'file',
                'hide' => 'yes',
            ],
            'other_document' => [
                'title' => '其他文档',
                'templet' => 'files',
                'hide' => 'yes',
            ],
            'create_time' => [
                'title' => '添加时间',
                'align' => 'center',
                'templet' => 'datetime',
                'hide' => 'yes',
                'sort' => true,
            ],
            'last_update_time' => [
                'title' => '上次更新时间',
                'align' => 'center',
                'templet' => 'datetime',
                'sort' => true,
            ],
            'action' => [
                'title' => '操作',
                'fixed' => "right",
                'templet' => 'action',
                'options' => [
                    'edit' => ['type' => 'openPopup', 'title' => '详情', 'icon' => 'layui-icon layui-icon-survey', 'url' => url('edit')],
                ]
            ]
        ];
        switch ($state) {
            case State::NORMAL:
                $cols['action']['options'] += [
                    State::RECYLE_BIN => ['title' => '移入回收站', 'dropdown' => true],
                ];
                break;
            case State::RECYLE_BIN:
                $cols['action']['options'] += [
                    State::NORMAL => ['title' => '恢复正常', 'dropdown' => true],
                    State::DELETED => ['title' => '永久删除', 'dropdown' => true]
                ];
                break;
        }
        return $cols;
    }

    /**
     * Notes: 列表筛选条件where集合
     * Author: Uncle-L
     * Date: 2021/11/15
     * Time: 12:02
     * @param array $filter
     * @return array
     */
    private function listWhere(array $filter): array {
        $state = $filter['state'];
        $ids = $filter['ids'];
        $name = $filter['name'];
        $grade = $filter['grade'];
        $where = [];
        $where[] = $state ? ['state', 'eq', $state] : ['state', 'neq', State::DELETED];
        if ($ids) $where[] = ['id', 'in', $ids];
        if ($name) $where[] = ['name', 'like', "%{$name}%"];
        if ($grade) $where[] = ['grade', 'eq', $grade];
        return $where;
    }

    /**
     * Notes: 数量
     * Author: Uncle-L
     * Date: 2021/11/14
     * Time: 13:50
     * @param array $filter [筛选条件]
     * @return int
     */
    public function count(array $filter): int {
        $where = $this->listWhere($filter);
        return $this->getUserModel()->getOwnCount($where);
    }

    /**
     * Notes: 数据项
     * Author: Uncle-L
     * Date: 2021/11/15
     * Time: 12:05
     * @param int $limitStart
     * @param int $limitLength
     * @param array $filter
     * @param array $sort
     * @return array
     */
    public function items(int $limitStart, int $limitLength, array $filter, array $sort): array {
        $where = $this->listWhere($filter);
        $order = $sort + ['id' => 'desc'];
        $items = $this->getUserModel()->getOwnRows($where, ["*"], $order, $limitStart, $limitLength);
        foreach ($items as &$v) {
            $v['area'] = ['province' => $v['province'], 'city' => $v['city'], 'district' => $v['district']];
        }
        return $items;
    }

    /**
     * Notes: 异步事件
     * Author: Uncle-L
     * Date: 2021/11/15
     * Time: 15:02
     * @param $event
     * @param array $ids
     * @return bool|string
     */
    public function event($event, array $ids) {
        if (is_numeric($event)) $event = (int)$event;
        if (!State::isValue($event)) return "事件异常，请刷新页面尝试此操作";
        if (!is_positive_int_array($ids)) return "数据异常，请刷新页面尝试此操作";
        $this->getUserModel()->change(["state" => $event], [
            ["id", "in", $ids],
            ["state", "neq", State::DELETED],
        ]);
        return true;
    }

    /**
     * Notes: 获取所有兴趣分类数据项
     * Author: Uncle-L
     * Date: 2021/11/15
     * Time: 11:52
     * @return array
     */
    private function getAllInterestCateItems(): array {
        static $items;
        if (!$items) $items = $this->getInterestCateModel()->getOwnRows();
        return $items;
    }

    /**
     * Notes: 获取兴趣分类id和name的数组
     * Author: Uncle-L
     * Date: 2021/11/15
     * Time: 11:51
     * @return array
     */
    public function getInterestCateIdNameOptions(): array {
        static $options;
        if (!$options) {
            $items = $this->getAllInterestCateItems();
            $options = array_combine(array_column($items, "id"), array_column($items, "name"));
        }
        return $options;
    }

    /**
     * Notes: 切换栏
     * Author: Uncle-L
     * Date: 2021/11/15
     * Time: 16:34
     * @return array
     */
    public function tab(): array {
        return ["base" => "基础", "other" => "其他"];
    }

    /**
     * Notes: 表单字段
     * Author: Uncle-L
     * Date: 2021/11/15
     * Time: 16:37
     * @param $tab
     * @param bool $isEdit
     * @return array
     */
    public function field($tab, $isEdit = false): array {
        $field = [];
        switch ($tab) {
            case "base":
                $field = [
                    "avatar" => [
                        "title" => "头像",
                        "type" => "img",
                    ],
                    "name" => [
                        "title" => "姓名",
                        "type" => "text",
                        "default" => "某某人",
                        "verify" => "require|chsDash",
                        "desc" => '必须，允许键入汉字/字母/数字/下划线/破折号-'
                    ],
                    "sex" => [
                        "title" => "性别",
                        "type" => "radio",
                        "options" => Sex::getTitleMap(),
                        "verify" => "require",
                    ],
                    "age" => [
                        "title" => "年龄",
                        "default" => 18,
                        "verify" => "require|positiveInt",
                    ],
                    "grade" => [
                        "title" => "年级",
                        "type" => "select",
                        "options" => Grade::getTitleMap(),
                    ],
                    "hobby" => [
                        "title" => "爱好",
                        "type" => "checkbox",
                        "options" => Hobby::getTitleMap()
                    ],
                    "area" => [
                        "title" => "地址",
                        "type" => "area",
                        "verify" => "require",
                    ],
                    "intro" => [
                        "title" => "个人介绍",
                        "type" => "textarea",
                        "default" => "某某人的个人介绍",
                        "verify" => "max:200",
                        "desc" => '限制200字符'
                    ],
                ];
                break;
            case "other":
                $field = [
                    "interest_cate_ids" => [
                        "title" => "感兴趣的分类",
                        'type' => 'tree',
                        'nodes' => $this->getAllInterestCateItems()
                    ],
                    "friend_ids" => [
                        "title" => "朋友",
                        'type' => 'dropdownSearch',
                        'verify' => 'arrayPositiveInt',
                        'url' => url('userDropdownSearchOptions'),
                    ],
                    "color" => [
                        "title" => "喜欢的颜色",
                        "type" => "color",
                    ],
                    "album" => [
                        "title" => "相册",
                        "type" => "imgs",
                    ],
                    'document' => [
                        'title' => '个人文档',
                        'type' => 'file',
                    ],
                    'other_document' => [
                        'title' => '其他文档',
                        'type' => 'files',
                    ],
                ];
                break;
        }
        if ($isEdit) array_insert($field, [
            "id" => [
                "title" => "用户",
                "type" => "hidden",
                "verify" => "require|positiveInt",
            ]
        ], "avatar");
        return $field;
    }

    /**
     * Notes: 数据获取
     * Author: Uncle-L
     * Date: 2021/11/16
     * Time: 10:45
     * @param int|null $id
     * @return array
     */
    public function load(int $id = null): array {
        $id = $id ?: input("get.id/d");
        $data = $this->getUserModel()->getOwnRow([
            ["id", "eq", $id],
            ["state", "neq", State::DELETED],
        ]);
        if (!$data) return [];
        $data['area'] = ['province' => $data['province'], 'city' => $data['city'], 'district' => $data['district']];
        return $data;
    }

    /**
     * Notes: 表单提交
     * Author: Uncle-L
     * Date: 2021/11/15
     * Time: 17:39
     * @param array $data
     * @param false $isEdit
     * @return bool
     */
    public function submit(array $data, $isEdit = false): bool {
        $saveData = [
            'avatar' => $data['avatar'],
            'name' => $data['name'],
            'sex' => $data['sex'],
            'age' => $data['age'],
            'grade' => $data['grade'],
            'hobby' => $data['hobby'] ? implode(',', $data['hobby']) : "",
            'province' => $data['area'] && isset($data['area']['province']) ? $data['area']['province'] : '',
            'city' => $data['area'] && isset($data['area']['city']) ? $data['area']['city'] : '',
            'district' => $data['area'] && isset($data['area']['district']) ? $data['area']['district'] : '',
            'intro' => $data['intro'],
            'interest_cate_ids' => $data['interest_cate_ids'] ? json_encode($data['interest_cate_ids']) : '',
            'friend_ids' => $data['friend_ids'] ? json_encode($data['friend_ids']) : '',
            'color' => $data['color'],
            'album' => $data['album'] ? implode(',', $data['album']) : "",
            'document' => $data['document'] ? json_encode($data['document']) : '',
            'other_document' => $data['other_document'] ? json_encode($data['other_document']) : '',
        ];
        if ($isEdit) {
            $saveData["id"] = $data["id"];
            $res = $this->getUserModel()->change($saveData);
        } else {
            $res = $this->getUserModel()->addRow($saveData);
        }
        return !!$res;
    }

    /**
     * Notes: 用户下拉搜索
     * Author: Uncle-L
     * Date: 2021/11/15
     * Time: 17:47
     * @param array $param
     * @return array
     */
    public function userDropdownSearchOptions(array $param = []): array {
        $param = $param ?: input('get.');
        $ids = filter_sql($param['ids']);
        $keywords = filter_sql($param['keywords']);

        $where = [];
        if ($ids) $where[] = ['id', 'in', $ids];
        if ($keywords) $where[] = ['name', 'like', "%{$keywords}%"];
        $field = ['id', 'name'];
        $datas = $this->getUserModel()->getOwnRows($where, $field, ["id" => "desc"], 0, 20);
        $items = array_combine(array_column($datas, "id"), array_column($datas, "name"));
        return $items;
    }

    /**
     * Notes: 工作表
     * Author: Uncle-L
     * Date: 2021/11/16
     * Time: 13:45
     * @return array
     */
    public function sheet(): array {
        return ["一年级", "二年级", "三年级", "四年级"];
    }

    /**
     * Notes: 导入表头
     * Author: Uncle-L
     * Date: 2021/11/14
     * Time: 13:42
     * @param $sheet [工作表]
     * @return array
     */
    public function importCols($sheet): array {
        $cols = [
            'name' => [
                "title" => '姓名',
                "default" => "某某人",
                "verify" => "require|chsDash",
                "desc" => '必填，允许输入汉字/字母/数字/下划线/破折号-'
            ],
            'sex' => [
                "title" => '性别',
                'default' => '男',
                'verify' => 'require|in:男,女',
                "desc" => "必填，男/女",
            ],
            'age' => [
                "title" => '年龄',
                'default' => '18',
                'verify' => 'require|positiveInt',
                "desc" => "必填，正整数",
            ],
            "hobby" => [
                "title" => "爱好",
                'default' => '阅读',
                'verify' => 'in:写作,阅读',
                "desc" => "写作/阅读",
            ],
            'intro' => [
                "title" => '简介',
                'default' => '个人简介',
                'verify' => 'max:200',
                "desc" => "限制200字符，如：姓名、曾用名、出生日期、籍贯、出生地、民族、现有文化程度、家庭现住址、现在工作单位和担任的社会职务、有何专业技术职称等基本情况。",
            ],
        ];
        return $cols;
    }

    /**
     * Notes: 多行数据处理
     * Author: Uncle-L
     * Date: 2021/11/16
     * Time: 14:27
     * @param array $rowsData
     * @return  mixed|string|array
     */
    public function rows(array $rowsData) {
        $datas = [];
        foreach ($rowsData as $id => $data) {
            $sheet = $data["sheet"];
            $rowData = $data["row"];
            $datas[] = [
                    "name" => $rowData["name"],
                    "sex" => Sex::getValueByTitle($rowData["sex"]),
                    "age" => $rowData["age"],
                    "grade" => Grade::getValueByTitle($sheet),
                    "hobby" => Hobby::getValueByTitle($rowData["hobby"]),
                    "intro" => $rowData["intro"],
                ] + $data["row"];
        }
        $this->getUserModel()->addRows($datas);
    }

}